Skip to content

Conversation

@AndyEveritt
Copy link
Contributor

@AndyEveritt AndyEveritt commented Sep 24, 2025

This adds support for merging template frontmatter when using tp.file.include

eg:

Root

---
some_frontmatter:
root_func: <% tp.date.now() %>
not_overwritten: 1
overwritten: 1
---
<%- tp.file.include("[[Sub]]") %>

top content

Sub

---
sub: 2
not_overwritten:
overwritten: 2
---

sub content
<% tp.file.include("[[Sub 2]]") %>

Sub 2

---
sub_func: <% tp.date.now() %>
---
sub 2 content

The expected output for this template is

---
some_frontmatter:
root_func: 2025-09-24
not_overwritten: 1
overwritten: 2
sub_func: 2025-09-24
sub: 2
---
sub content
sub 2 content

top content

This also works with tp.file.create_new() and files created with Bases

@AndyEveritt
Copy link
Contributor Author

AndyEveritt commented Sep 24, 2025

For details on how this feature works:

  • The frontmatter for the template is maintained separately from the contents of the template by adding a new field to RunningConfig called frontmatter
  • Parsing of <% tp... %> blocks is executed
    • Any tp.file.include has it's frontmatter processed, merged into the running_config.frontmatter, and removed from the included content
  • Once parsing of the root template has finished, any frontmatter is extracted
    • It is done at this point so tp functions like tp.date.now() are still parsed correctly
  • The running_config.frontmatter is merged into the root frontmatter and running_config.frontmatter is updated with the result
    • It is done this way so included templates overwrite the parent if they have overlapping property keys
  • The running_config.frontmatter is now a parsed & merged frontmatter for the root and all included templates
  • Depending on how templater was initiated the following happens:
    • create_new_note_from_template(): this is from tp.file.create_new() or the Obsidian command Templater: Create new note from template, the output_content is updated to have the merged frontmatter
    • append_template_to_active_file(): the merged template frontmatter is merged into any existing file frontmatter
    • write_template_to_file: frontmatter is merged with existing file frontmatter. Existing file frontmatter will typically only exist if the file was created by a Base

@AndyEveritt
Copy link
Contributor Author

Btw I think there is a fundamental issue with the config system in Templater. When you have nested calls such as a tp.file.create_new() inside a template included with tp.file.include(), the config for create_new overwrites the config for include so even after the create_new has finished processing, the include config is uses the create_new config.

This essentially means that config.target_file, config.active_file and the new config.frontmatter are now pointing to the wrong thing which will cause various weird issues.

In this case it means if you have a template which is includes another template that creates a file, the frontmatter of the template which creates the file won't be merged into the frontmatter of the root template.

@AndyEveritt
Copy link
Contributor Author

I've fixed the config issue by creating a new instance of the modules in functions_object each time the Templater.parse_template() is called. Before a singleton was used for each InternalModule which was leading to issues as the configs were getting overwritten

@AndyEveritt
Copy link
Contributor Author

@Zachatoo have you had a chance to review this?

@Zachatoo
Copy link
Collaborator

Sorry I have not! I'll need to do some testing with this, hopefully I'll have time this weekend

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants